package com.shrct.businessprocess.purchase.impl;

import com.google.common.base.Objects;
import com.google.common.collect.Iterables;
import com.shrct.businessprocess.diagnose.IDiagnoseAcceptor;
import com.shrct.businessprocess.money.Moneys;
import com.shrct.businessprocess.product.RCProductEntry;
import com.shrct.businessprocess.product.RCProductSpecification;
import com.shrct.businessprocess.project.RCExchangeRate;
import com.shrct.businessprocess.project.RCProjectMoney;
import com.shrct.businessprocess.purchase.RCBaseProductPurchaseBudget;
import com.shrct.businessprocess.purchase.RCHasPurchaseBudget;
import com.shrct.businessprocess.purchase.RCProductPurchaseRequest;
import com.shrct.businessprocess.purchase.RCProductPurchaseRequestItem;
import com.shrct.businessprocess.purchase.RCPurchaseOrder;
import com.shrct.businessprocess.purchase.RCPurchaseOrderItem;
import com.shrct.businessprocess.purchase.RCPurchaseOrderStatus;
import com.shrct.businessprocess.purchase.impl.RCBasePurchaseRequestImpl;
import com.shrct.businessprocess.purchase.impl.RCProductPurchaseRequestItemImpl;
import com.shrct.businessprocess.purchase.impl.RCPurchaseOrderImpl;
import com.shrct.businessprocess.purchase.proxy.RCProductPurchaseRequestProxy;
import edu.fudan.mylang.common.NumberExtensions;
import edu.fudan.mylang.pf.IObjectFactory;
import java.util.Collection;
import javax.persistence.CascadeType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.Functions.Function2;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;

@Entity
@DiscriminatorValue("RCPRODUCTPURCHASEREQUEST_TYPE")
public class RCProductPurchaseRequestImpl extends RCBasePurchaseRequestImpl implements RCProductPurchaseRequest {
  public RCProductPurchaseRequestImpl() {
    super();
  }
  
  public RCProductPurchaseRequestImpl(final RCHasPurchaseBudget budget) {
    super( budget);
    
  }
  
  @OneToMany(targetEntity = RCProductPurchaseRequestItemImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, mappedBy = "purchaseRequest")
  private Collection<RCProductPurchaseRequestItem> items = new java.util.ArrayList<com.shrct.businessprocess.purchase.RCProductPurchaseRequestItem>();;
  
  public Collection<RCProductPurchaseRequestItem> getItems() {
    return this.items;
  }
  
  public RCProductPurchaseRequestItem createAndAddtoItems() {
    getItems().size();
    com.shrct.businessprocess.purchase.RCProductPurchaseRequestItem rCProductPurchaseRequestItem = new com.shrct.businessprocess.purchase.impl.RCProductPurchaseRequestItemImpl(this);
    getObjectFactory().create(rCProductPurchaseRequestItem);
    getItems().add(rCProductPurchaseRequestItem);
    return rCProductPurchaseRequestItem;
    
  }
  
  public RCProductPurchaseRequestItem createAndAddtoItems(final Procedure1<RCProductPurchaseRequestItem> updater) {
    getItems().size();
    com.shrct.businessprocess.purchase.RCProductPurchaseRequestItem rCProductPurchaseRequestItem = new com.shrct.businessprocess.purchase.impl.RCProductPurchaseRequestItemImpl(this);
    getObjectFactory().create(rCProductPurchaseRequestItem);
    getItems().add(rCProductPurchaseRequestItem);
    return rCProductPurchaseRequestItem;
    
  }
  
  public RCProductPurchaseRequest removeAllItems() {
    for(RCProductPurchaseRequestItem obj : this.items){
    	getObjectFactory().delete(obj);
    }
    this.items.clear();
    return this;	
    
  }
  
  public RCProductPurchaseRequest removeFromItems(final RCProductPurchaseRequestItem rCProductPurchaseRequestItem) {
    this.items.remove(rCProductPurchaseRequestItem);
    getObjectFactory().delete(rCProductPurchaseRequestItem);
    return this;
    
  }
  
  @OneToMany(targetEntity = RCPurchaseOrderImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, mappedBy = "purchaseRequest")
  private Collection<RCPurchaseOrder> purchaseOrders = new java.util.ArrayList<com.shrct.businessprocess.purchase.RCPurchaseOrder>();;
  
  public Collection<RCPurchaseOrder> getPurchaseOrders() {
    return this.purchaseOrders;
  }
  
  public RCPurchaseOrder createAndAddtoPurchaseOrders() {
    getPurchaseOrders().size();
    com.shrct.businessprocess.purchase.RCPurchaseOrder rCPurchaseOrder = new com.shrct.businessprocess.purchase.impl.RCPurchaseOrderImpl(this);
    getObjectFactory().create(rCPurchaseOrder);
    getPurchaseOrders().add(rCPurchaseOrder);
    return rCPurchaseOrder;
    
  }
  
  public RCPurchaseOrder createAndAddtoPurchaseOrders(final Procedure1<RCPurchaseOrder> updater) {
    getPurchaseOrders().size();
    com.shrct.businessprocess.purchase.RCPurchaseOrder rCPurchaseOrder = new com.shrct.businessprocess.purchase.impl.RCPurchaseOrderImpl(this);
    getObjectFactory().create(rCPurchaseOrder);
    getPurchaseOrders().add(rCPurchaseOrder);
    return rCPurchaseOrder;
    
  }
  
  public RCProductPurchaseRequest removeAllPurchaseOrders() {
    for(RCPurchaseOrder obj : this.purchaseOrders){
    	getObjectFactory().delete(obj);
    }
    this.purchaseOrders.clear();
    return this;	
    
  }
  
  public RCProductPurchaseRequest removeFromPurchaseOrders(final RCPurchaseOrder rCPurchaseOrder) {
    this.purchaseOrders.remove(rCPurchaseOrder);
    getObjectFactory().delete(rCPurchaseOrder);
    return this;
    
  }
  
  public RCBaseProductPurchaseBudget getBudget() {
    RCHasPurchaseBudget _budget = super.getBudget();
    return ((RCBaseProductPurchaseBudget) _budget);
  }
  
  /**
   * 计算是否所有请购的内容都已经订购
   */
  public Boolean calcIsOrderFinished() {
    Boolean _xblockexpression = null;
    {
      final Function1<RCProductPurchaseRequestItem,Boolean> _function = new Function1<RCProductPurchaseRequestItem,Boolean>() {
          public Boolean apply(final RCProductPurchaseRequestItem it) {
            RCProductSpecification _productSpec = it.getProductSpec();
            Integer _totalPassedOrderItemsQuantity = RCProductPurchaseRequestImpl.this.getTotalPassedOrderItemsQuantity(_productSpec);
            Integer _quantity = it.getQuantity();
            boolean _greaterEqualsThan = (_totalPassedOrderItemsQuantity.compareTo(_quantity) >= 0);
            return Boolean.valueOf(_greaterEqualsThan);
          }
        };
      boolean _forall = IterableExtensions.<RCProductPurchaseRequestItem>forall(this.items, _function);
      this.setIsFinished(Boolean.valueOf(_forall));
      Boolean _isFinished = this.getIsFinished();
      _xblockexpression = (_isFinished);
    }
    return _xblockexpression;
  }
  
  public RCPurchaseOrder createOrder() {
    RCPurchaseOrder _createAndAddtoPurchaseOrders = this.createAndAddtoPurchaseOrders();
    final Procedure1<RCPurchaseOrder> _function = new Procedure1<RCPurchaseOrder>() {
        public void apply(final RCPurchaseOrder it) {
          it.start();
        }
      };
    RCPurchaseOrder _doubleArrow = ObjectExtensions.<RCPurchaseOrder>operator_doubleArrow(_createAndAddtoPurchaseOrders, _function);
    return _doubleArrow;
  }
  
  public void deleteOrder(final RCPurchaseOrder o) {
    RCPurchaseOrderStatus _status = o.getStatus();
    final RCPurchaseOrderStatus _switchValue = _status;
    boolean _matched = false;
    if (!_matched) {
      if (Objects.equal(_switchValue,RCPurchaseOrderStatus.craeted)) {
        _matched=true;
        this.removeFromPurchaseOrders(o);
      }
    }
    if (!_matched) {
      RuntimeException _runtimeException = new RuntimeException("Invalid Status");
      throw _runtimeException;
    }
  }
  
  public Integer getTotalOrderItemsQuantity() {
    final Function1<RCPurchaseOrder,Boolean> _function = new Function1<RCPurchaseOrder,Boolean>() {
        public Boolean apply(final RCPurchaseOrder it) {
          Boolean _isInitialized = it.getIsInitialized();
          return _isInitialized;
        }
      };
    Iterable<RCPurchaseOrder> _filter = IterableExtensions.<RCPurchaseOrder>filter(this.purchaseOrders, _function);
    final Function1<RCPurchaseOrder,Collection<RCPurchaseOrderItem>> _function_1 = new Function1<RCPurchaseOrder,Collection<RCPurchaseOrderItem>>() {
        public Collection<RCPurchaseOrderItem> apply(final RCPurchaseOrder it) {
          Collection<RCPurchaseOrderItem> _orderItems = it.getOrderItems();
          return _orderItems;
        }
      };
    Iterable<Collection<RCPurchaseOrderItem>> _map = IterableExtensions.<RCPurchaseOrder, Collection<RCPurchaseOrderItem>>map(_filter, _function_1);
    Iterable<RCPurchaseOrderItem> _flatten = Iterables.<RCPurchaseOrderItem>concat(_map);
    final Function1<RCPurchaseOrderItem,Integer> _function_2 = new Function1<RCPurchaseOrderItem,Integer>() {
        public Integer apply(final RCPurchaseOrderItem it) {
          Integer _quantity = it.getQuantity();
          return _quantity;
        }
      };
    Iterable<Integer> _map_1 = IterableExtensions.<RCPurchaseOrderItem, Integer>map(_flatten, _function_2);
    final Function2<Integer,Integer,Integer> _function_3 = new Function2<Integer,Integer,Integer>() {
        public Integer apply(final Integer i1, final Integer i2) {
          int _plus = ((i1).intValue() + (i2).intValue());
          return Integer.valueOf(_plus);
        }
      };
    Integer _reduce = IterableExtensions.<Integer>reduce(_map_1, _function_3);
    Integer _nullsafe = NumberExtensions.nullsafe(_reduce);
    return _nullsafe;
  }
  
  public Integer getTotalPassedOrderItemsQuantity(final RCProductSpecification productSpec) {
    final Function1<RCPurchaseOrder,Boolean> _function = new Function1<RCPurchaseOrder,Boolean>() {
        public Boolean apply(final RCPurchaseOrder it) {
          boolean _and = false;
          Boolean _isInitialized = it.getIsInitialized();
          if (!(_isInitialized).booleanValue()) {
            _and = false;
          } else {
            Boolean _isCanceled = it.isCanceled();
            boolean _not = (!_isCanceled);
            _and = ((_isInitialized).booleanValue() && _not);
          }
          return Boolean.valueOf(_and);
        }
      };
    Iterable<RCPurchaseOrder> _filter = IterableExtensions.<RCPurchaseOrder>filter(this.purchaseOrders, _function);
    final Function1<RCPurchaseOrder,Collection<RCPurchaseOrderItem>> _function_1 = new Function1<RCPurchaseOrder,Collection<RCPurchaseOrderItem>>() {
        public Collection<RCPurchaseOrderItem> apply(final RCPurchaseOrder it) {
          Collection<RCPurchaseOrderItem> _orderItems = it.getOrderItems();
          return _orderItems;
        }
      };
    Iterable<Collection<RCPurchaseOrderItem>> _map = IterableExtensions.<RCPurchaseOrder, Collection<RCPurchaseOrderItem>>map(_filter, _function_1);
    Iterable<RCPurchaseOrderItem> _flatten = Iterables.<RCPurchaseOrderItem>concat(_map);
    final Function1<RCPurchaseOrderItem,Boolean> _function_2 = new Function1<RCPurchaseOrderItem,Boolean>() {
        public Boolean apply(final RCPurchaseOrderItem it) {
          RCProductSpecification _productSpec = it.getProductSpec();
          boolean _equals = Objects.equal(_productSpec, productSpec);
          return Boolean.valueOf(_equals);
        }
      };
    Iterable<RCPurchaseOrderItem> _filter_1 = IterableExtensions.<RCPurchaseOrderItem>filter(_flatten, _function_2);
    final Function1<RCPurchaseOrderItem,Integer> _function_3 = new Function1<RCPurchaseOrderItem,Integer>() {
        public Integer apply(final RCPurchaseOrderItem it) {
          Integer _quantity = it.getQuantity();
          return _quantity;
        }
      };
    Iterable<Integer> _map_1 = IterableExtensions.<RCPurchaseOrderItem, Integer>map(_filter_1, _function_3);
    final Function2<Integer,Integer,Integer> _function_4 = new Function2<Integer,Integer,Integer>() {
        public Integer apply(final Integer i1, final Integer i2) {
          int _plus = ((i1).intValue() + (i2).intValue());
          return Integer.valueOf(_plus);
        }
      };
    Integer _reduce = IterableExtensions.<Integer>reduce(_map_1, _function_4);
    Integer _nullsafe = NumberExtensions.nullsafe(_reduce);
    return _nullsafe;
  }
  
  public Integer getTotalOrderItemsQuantity(final RCProductSpecification productSpec) {
    final Function1<RCPurchaseOrder,Boolean> _function = new Function1<RCPurchaseOrder,Boolean>() {
        public Boolean apply(final RCPurchaseOrder it) {
          Boolean _isCanceled = it.isCanceled();
          boolean _not = (!_isCanceled);
          return Boolean.valueOf(_not);
        }
      };
    Iterable<RCPurchaseOrder> _filter = IterableExtensions.<RCPurchaseOrder>filter(this.purchaseOrders, _function);
    final Function1<RCPurchaseOrder,Collection<RCPurchaseOrderItem>> _function_1 = new Function1<RCPurchaseOrder,Collection<RCPurchaseOrderItem>>() {
        public Collection<RCPurchaseOrderItem> apply(final RCPurchaseOrder it) {
          Collection<RCPurchaseOrderItem> _orderItems = it.getOrderItems();
          return _orderItems;
        }
      };
    Iterable<Collection<RCPurchaseOrderItem>> _map = IterableExtensions.<RCPurchaseOrder, Collection<RCPurchaseOrderItem>>map(_filter, _function_1);
    Iterable<RCPurchaseOrderItem> _flatten = Iterables.<RCPurchaseOrderItem>concat(_map);
    final Function1<RCPurchaseOrderItem,Boolean> _function_2 = new Function1<RCPurchaseOrderItem,Boolean>() {
        public Boolean apply(final RCPurchaseOrderItem it) {
          RCProductSpecification _productSpec = it.getProductSpec();
          boolean _equals = Objects.equal(_productSpec, productSpec);
          return Boolean.valueOf(_equals);
        }
      };
    Iterable<RCPurchaseOrderItem> _filter_1 = IterableExtensions.<RCPurchaseOrderItem>filter(_flatten, _function_2);
    final Function1<RCPurchaseOrderItem,Integer> _function_3 = new Function1<RCPurchaseOrderItem,Integer>() {
        public Integer apply(final RCPurchaseOrderItem it) {
          Integer _quantity = it.getQuantity();
          return _quantity;
        }
      };
    Iterable<Integer> _map_1 = IterableExtensions.<RCPurchaseOrderItem, Integer>map(_filter_1, _function_3);
    final Function2<Integer,Integer,Integer> _function_4 = new Function2<Integer,Integer,Integer>() {
        public Integer apply(final Integer i1, final Integer i2) {
          int _plus = ((i1).intValue() + (i2).intValue());
          return Integer.valueOf(_plus);
        }
      };
    Integer _reduce = IterableExtensions.<Integer>reduce(_map_1, _function_4);
    Integer _nullsafe = NumberExtensions.nullsafe(_reduce);
    return _nullsafe;
  }
  
  public Integer getTotalAcceptItemsQuantity() {
    final Function1<RCPurchaseOrder,Integer> _function = new Function1<RCPurchaseOrder,Integer>() {
        public Integer apply(final RCPurchaseOrder it) {
          Integer _totalAcceptItemsQuantity = it.getTotalAcceptItemsQuantity();
          return _totalAcceptItemsQuantity;
        }
      };
    Iterable<Integer> _map = IterableExtensions.<RCPurchaseOrder, Integer>map(this.purchaseOrders, _function);
    final Function2<Integer,Integer,Integer> _function_1 = new Function2<Integer,Integer,Integer>() {
        public Integer apply(final Integer i1, final Integer i2) {
          int _plus = ((i1).intValue() + (i2).intValue());
          return Integer.valueOf(_plus);
        }
      };
    Integer _reduce = IterableExtensions.<Integer>reduce(_map, _function_1);
    Integer _nullsafe = NumberExtensions.nullsafe(_reduce);
    return _nullsafe;
  }
  
  public Integer getTotalAcceptItemsQuantity(final RCProductSpecification productSpec) {
    final Function1<RCPurchaseOrder,Integer> _function = new Function1<RCPurchaseOrder,Integer>() {
        public Integer apply(final RCPurchaseOrder it) {
          Integer _totalAcceptItemsQuantity = it.getTotalAcceptItemsQuantity(productSpec);
          return _totalAcceptItemsQuantity;
        }
      };
    Iterable<Integer> _map = IterableExtensions.<RCPurchaseOrder, Integer>map(this.purchaseOrders, _function);
    final Function2<Integer,Integer,Integer> _function_1 = new Function2<Integer,Integer,Integer>() {
        public Integer apply(final Integer i1, final Integer i2) {
          int _plus = ((i1).intValue() + (i2).intValue());
          return Integer.valueOf(_plus);
        }
      };
    Integer _reduce = IterableExtensions.<Integer>reduce(_map, _function_1);
    Integer _nullsafe = NumberExtensions.nullsafe(_reduce);
    return _nullsafe;
  }
  
  public RCProjectMoney getTotalOrderAmount() {
    final Function1<RCPurchaseOrder,Boolean> _function = new Function1<RCPurchaseOrder,Boolean>() {
        public Boolean apply(final RCPurchaseOrder it) {
          Boolean _isInitialized = it.getIsInitialized();
          return _isInitialized;
        }
      };
    Iterable<RCPurchaseOrder> _filter = IterableExtensions.<RCPurchaseOrder>filter(this.purchaseOrders, _function);
    final Function1<RCPurchaseOrder,RCProjectMoney> _function_1 = new Function1<RCPurchaseOrder,RCProjectMoney>() {
        public RCProjectMoney apply(final RCPurchaseOrder it) {
          RCProjectMoney _totalCost = it.getTotalCost();
          return _totalCost;
        }
      };
    Iterable<RCProjectMoney> _map = IterableExtensions.<RCPurchaseOrder, RCProjectMoney>map(_filter, _function_1);
    RCExchangeRate _exchangeRate = this.getExchangeRate();
    RCProjectMoney _sum = Moneys.sum(_map, _exchangeRate);
    return _sum;
  }
  
  public RCProjectMoney getTotalPessimisticOrderAmount() {
    final Function1<RCPurchaseOrder,Boolean> _function = new Function1<RCPurchaseOrder,Boolean>() {
        public Boolean apply(final RCPurchaseOrder it) {
          Boolean _isCanceled = it.isCanceled();
          boolean _not = (!_isCanceled);
          return Boolean.valueOf(_not);
        }
      };
    Iterable<RCPurchaseOrder> _filter = IterableExtensions.<RCPurchaseOrder>filter(this.purchaseOrders, _function);
    final Function1<RCPurchaseOrder,RCProjectMoney> _function_1 = new Function1<RCPurchaseOrder,RCProjectMoney>() {
        public RCProjectMoney apply(final RCPurchaseOrder it) {
          RCProjectMoney _totalCost = it.getTotalCost();
          return _totalCost;
        }
      };
    Iterable<RCProjectMoney> _map = IterableExtensions.<RCPurchaseOrder, RCProjectMoney>map(_filter, _function_1);
    RCExchangeRate _exchangeRate = this.getExchangeRate();
    RCProjectMoney _sum = Moneys.sum(_map, _exchangeRate);
    return _sum;
  }
  
  public RCProjectMoney getTotalRequestedAmount() {
    RCProjectMoney _expectCost = this.getExpectCost();
    return _expectCost;
  }
  
  public RCExchangeRate getExchangeRate() {
    RCBaseProductPurchaseBudget _budget = this.getBudget();
    RCExchangeRate _defaultPurchaseExchangeRate = _budget.getDefaultPurchaseExchangeRate();
    return _defaultPurchaseExchangeRate;
  }
  
  public void diagnose(final IDiagnoseAcceptor acceptor) {
    final Procedure1<RCPurchaseOrder> _function = new Procedure1<RCPurchaseOrder>() {
        public void apply(final RCPurchaseOrder pruchaseOrder) {
          pruchaseOrder.diagnose(acceptor);
        }
      };
    IterableExtensions.<RCPurchaseOrder>forEach(this.purchaseOrders, _function);
  }
  
  public Iterable<RCProductEntry> getAllAcceptedProducts() {
    final Function1<RCPurchaseOrder,Iterable<RCProductEntry>> _function = new Function1<RCPurchaseOrder,Iterable<RCProductEntry>>() {
        public Iterable<RCProductEntry> apply(final RCPurchaseOrder it) {
          Iterable<RCProductEntry> _allAcceptedProducts = it.getAllAcceptedProducts();
          return _allAcceptedProducts;
        }
      };
    Iterable<Iterable<RCProductEntry>> _map = IterableExtensions.<RCPurchaseOrder, Iterable<RCProductEntry>>map(this.purchaseOrders, _function);
    Iterable<RCProductEntry> _flatten = Iterables.<RCProductEntry>concat(_map);
    return _flatten;
  }
  
  public void auditPassed() {
    final RCProductPurchaseRequestImpl purchaseRequest = this;
    purchaseRequest.setIsPassed(Boolean.valueOf(true));
    RCBaseProductPurchaseBudget _budget = purchaseRequest.getBudget();
    _budget.purchaseRequestAuditPassed(purchaseRequest);
  }
  
  public static RCProductPurchaseRequest create(final RCHasPurchaseBudget budget, final IObjectFactory objectFactory) {
    com.shrct.businessprocess.purchase.RCProductPurchaseRequest rCProductPurchaseRequest = new com.shrct.businessprocess.purchase.impl.RCProductPurchaseRequestImpl(
    	budget
    );
    objectFactory.create(rCProductPurchaseRequest);
    return rCProductPurchaseRequest;			
    
  }
  
  public static RCProductPurchaseRequest createRCProductPurchaseRequestImpl(final RCHasPurchaseBudget budget, final IObjectFactory objectFactory, final Procedure1<RCProductPurchaseRequest> init) {
    com.shrct.businessprocess.purchase.RCProductPurchaseRequest rCProductPurchaseRequest = new com.shrct.businessprocess.purchase.impl.RCProductPurchaseRequestImpl(
    	budget
    );
    objectFactory.create(rCProductPurchaseRequest);
    init.apply(rCProductPurchaseRequest);
    
    return rCProductPurchaseRequest;			
    
  }
  
  public RCProductPurchaseRequestProxy toProxy() {
    com.shrct.businessprocess.purchase.proxy.RCProductPurchaseRequestProxy proxy = new com.shrct.businessprocess.purchase.proxy.RCProductPurchaseRequestProxy();
    proxy.setId(this.getId());
    if(this instanceof edu.fudan.mylang.pf.INamedModelObject){
    	proxy.setName(((edu.fudan.mylang.pf.INamedModelObject)this).getEntityName());
    }
    return proxy;
    
  }
}
